package com.ruoyi.common.modbus.message.factory;

import com.ruoyi.common.modbus.factory.MiiBytesFactory;
import com.ruoyi.common.modbus.message.MiiByteArrayMessage;
import com.ruoyi.common.modbus.message.MiiHmOutMessage;
import com.ruoyi.common.modbus.message.MiiMessage;
import com.ruoyi.common.modbus.utils.BytesToHexUtil;
import com.ruoyi.common.modbus.utils.ModbusCrc16Utils;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigInteger;

/**
 * 类功能说明：指令下发处理工厂<br/>
 * 公司名称：未可自动化 <br/>
 * 作者：weikeauto <br/>
 */
public class MiiOutMessageFactory<E> implements MiiMessageFactory<E> {

    private MiiBytesFactory<E> factory;

    public MiiOutMessageFactory(MiiBytesFactory<E> factory) {
        this.factory = factory;
    }

    @Override
    public MiiMessage buildMessage(String deviceGroup, E... datas) {
        byte[] bytes = factory.toBytes(datas);
        byte[] msg = new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + MiiHmOutMessage.CHECKCODE_SIZE];
        System.arraycopy(bytes, 0, msg, 0, bytes.length);
        byte[] checkData = ArrayUtils.subarray(msg, MiiHmOutMessage.DEVICE_INDEX, msg.length - 2);
        byte[] checkCodeBytes = ModbusCrc16Utils.getCrcByte(checkData);
        System.arraycopy(checkCodeBytes, 0, msg, msg.length - 2, checkCodeBytes.length);
        return new MiiByteArrayMessage(deviceGroup, msg);
    }

    @Override
    public MiiMessage buildStrMessage(Integer dataFormat, String deviceGroup, E datas) {
        byte[] bytes = BytesToHexUtil.hexToByteArray((String) datas);
        byte[] msg= null; //= new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + 5 + MiiHmOutMessage.CHECKCODE_SIZE];
        if (dataFormat == 1) {
            msg = new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + MiiHmOutMessage.CHECKCODE_SIZE];
        }else{
            msg = new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + 5 + MiiHmOutMessage.CHECKCODE_SIZE];
        }
        System.arraycopy(bytes, 0, msg, 0, bytes.length);
        byte[] checkData = ArrayUtils.subarray(msg, MiiHmOutMessage.DEVICE_INDEX, msg.length - 2);
        byte[] checkCodeBytes = ModbusCrc16Utils.getCrcByte(checkData);
        System.arraycopy(checkCodeBytes, 0, msg, msg.length - 2, checkCodeBytes.length);
        return new MiiByteArrayMessage(deviceGroup, msg);
    }

    @Override
    public MiiMessage buildChangeMessage(String deviceIp, E datas) {
        byte[] bytes = BytesToHexUtil.hexToByteArray( (String) datas);
        byte[] msg = new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + MiiHmOutMessage.CHECKCODE_SIZE];
        System.arraycopy(bytes, 0, msg, 0, bytes.length);
        byte[] checkData = ArrayUtils.subarray(msg, MiiHmOutMessage.DEVICE_INDEX, msg.length - 2);
        byte[] checkCodeBytes = ModbusCrc16Utils.getCrcByte(checkData);
        System.arraycopy(checkCodeBytes, 0, msg, msg.length - 2, checkCodeBytes.length);
        return new MiiByteArrayMessage(deviceIp, msg);
    }

    @Override
    public MiiMessage buildLocationMessage(String deviceIp, E datas) {
        byte[] bytes = BytesToHexUtil.hexToByteArray( (String) datas);
        return new MiiByteArrayMessage(deviceIp, bytes);
    }
//    @Override
//    public MiiMessage buildMessage(String deviceGroup, E... datas) {
////		byte[] bytes = factory.toBytes(datas);
//        int device = 0x01;
//        int functionCode = 0x03;
//        byte[] start = {(byte) 0x00, (byte) 0x00};
//        byte[] dataLength = {(byte) 0x00, (byte) 0x0A};
//        // 01 03 00 00 00 0A C5 CD
//        // 01030000000305cb
//        // 01030600000000424811e3
//        //010314 00000000 4246675e 00000000 00000000 00000000 65bd
//        // 第一个数据是阀门开关状态，第二个为电池容量，第三个为实时压力，第四个为实时流量，第五个为累计流量
//
//        byte[] msg = new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + MiiHmOutMessage.CHECKCODE_SIZE];
//        msg[MiiHmOutMessage.DEVICE_INDEX] = (byte) device;
//        msg[MiiHmOutMessage.FUNCODE_INDEX] = (byte) functionCode;
//        System.arraycopy(start, 0, msg, MiiHmOutMessage.START_INDEX, start.length);
////		byte[] lengthBytes = IntegerToByteUtil.intToByteArray(data.length, MiiHmOutMessage.DATA_LENGTH_SIZE);
////		System.arraycopy(lengthBytes, 0, msg, MiiHmOutMessage.DATA_LENGTH_INDEX, lengthBytes.length);
//        System.arraycopy(dataLength, 0, msg, MiiHmOutMessage.DATA_LENGTH_INDEX, dataLength.length);
//        byte[] checkData = ArrayUtils.subarray(msg, MiiHmOutMessage.DEVICE_INDEX, msg.length - 2);
//        byte[] checkCodeBytes = ModbusCrc16Utils.getCrcByte(checkData);
//        System.arraycopy(checkCodeBytes, 0, msg, msg.length - 2, checkCodeBytes.length);
//
//        return new MiiByteArrayMessage(deviceGroup, msg);
//    }


    public static void main(String[] args) {
        // 组装服务端请求客户端参数
        int device = 0x01;
        int functionCode = 0x06;
        byte[] start = {(byte) 0x00, (byte) 0x00};
        byte[] dataLength = {(byte) 0x00, (byte) 0x01};

        byte[] msg = new byte[MiiHmOutMessage.DEVICE_SIZE + MiiHmOutMessage.FUNCODE_SIZE + MiiHmOutMessage.START_SIZE + MiiHmOutMessage.DATA_LENGTH_SIZE + MiiHmOutMessage.CHECKCODE_SIZE];
        msg[MiiHmOutMessage.DEVICE_INDEX] = (byte) device;
        msg[MiiHmOutMessage.FUNCODE_INDEX] = (byte) functionCode;
        System.arraycopy(start, 0, msg, MiiHmOutMessage.START_INDEX, start.length);
//		byte[] lengthBytes = IntegerToByteUtil.intToByteArray(data.length, MiiHmOutMessage.DATA_LENGTH_SIZE);
//		System.arraycopy(lengthBytes, 0, msg, MiiHmOutMessage.DATA_LENGTH_INDEX, lengthBytes.length);
        System.arraycopy(dataLength, 0, msg, MiiHmOutMessage.DATA_LENGTH_INDEX, dataLength.length);
        byte[] checkData = ArrayUtils.subarray(msg, MiiHmOutMessage.DEVICE_INDEX, msg.length - 2);
        byte[] checkCodeBytes = ModbusCrc16Utils.getCrcByte(checkData);
        System.arraycopy(checkCodeBytes, 0, msg, msg.length - 2, checkCodeBytes.length);

        System.out.println(Hex.toHexString(msg));
        System.out.println(Hex.decode("0103000003000102036161"));
    }


    public static void main222(String[] args) {
//        int heartStart = 0xaa; // aa313233343536aa
//        int regNo = 0xbb;
//        String str = "1b";
//
//        BigInteger bigInteger = new BigInteger(str.getBytes());
//        String hexString1 = bigInteger.toString(16);
//        System.out.println(hexString1);
//
//        System.out.println(hexStringToString(hexString1));
//        System.out.println(Integer.toHexString(9));
//        System.out.println(String.format("%08x", 44.5)); 41b35de9
//        float floatValue = 1f;
//        int intBits = Float.floatToIntBits(floatValue);
//        String hexString = Integer.toHexString(intBits);
//        System.out.println("16进制表示: " + hexString);
    }

    public static void main23(String[] args) {
        String str = "00500824022300000377";
        String hex = convertToHex(str);
        System.out.println(hex);
        System.out.println(hexStringToString(hex));
        System.out.println(hexStringToString("3839383630343333313932324330303039393031"));

    }

    public static String convertToHex(String str) {
        StringBuilder hex = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            String hexString = Integer.toHexString(c);
            hex.append(hexString);
        }
        return hex.toString();
    }

    public static String hexStringToString(String hex) {
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i += 2) {
            bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
        }
        return new String(bytes);
    }
}
